package net.asfun.jvalog.common;

import static net.asfun.jvalog.common.log.logger;

import java.util.Date;

import com.google.appengine.api.datastore.Text;

import net.asfun.jvalog.entity.Store;
import net.asfun.jvalog.resource.StoreDao;


public class DualCacher {
	
	private static long hits = 0;
	private static long misses = 0;
	private static long byteFetched = 0;
	private static long byteStored = 0;
	private static int items;
	
	
	private DualCacher(){}
	
	static {
		items = StoreDao.count();
	}
	
	/**
	 * find cache 
	 * @param key uri
	 * @return null if none cache found
	 */
	public static String get(String key) {
		Object cache = GMCacher.get(key);
		if ( cache != null ) {
			return cache.toString();
		} else {
			Store store = StoreDao.getByItem(key);
			if ( store != null ) {
				String res = store.getValue().getValue();
				store.count();
				//TODO synchronized
				hits++;
				byteFetched += res.getBytes().length;
				GMCacher.put(key, res);
				return res;
			} else {
				//TODO synchronized
				misses++;
				return null;
			}
		}
	}
	
	public static void remove(String key) {
		GMCacher.remove(key);
		Store store = StoreDao.getByItem(key);
		if ( store != null ) {
			JdoerFactory.jdoStore.delete(store);
		}
	}
	
	/**
	 * save cache
	 * @param key
	 * @param value
	 */
	public static void put(String key, String value) {
		//TODO synchronized
		byteStored += value.getBytes().length;
		Store store = StoreDao.getByItem(key);
		if ( store == null ) {
			store = new Store();
			store.setDate(new Date());
			store.setItem(key);
			store.setValue(value);
			JdoerFactory.jdoStore.save(store);
			//TODO synchronized
			items++;
		} else {
			store.setDate(new Date());
			store.setValue(new Text(value));
		}
		logger.info("------------cache string for key=" + key);
	}

	public static String statMem() {
		return GMCacher.getStat();
	}
	
	public static String statDb() {
		StringBuffer buff = new StringBuffer();
		buff.append("Hits: ").append(hits)
			.append("\nMisses: ").append(misses)
			.append("\nBytes Fetched: ").append(byteFetched)
			.append("\nBytes Stored: ").append(byteStored)
			.append("\nItems: ").append(items)
			.append("\nMax Cached Time: N/A");
		return buff.toString();
	}
	
	public static void clearMem() {
		GMCacher.clear();
		logger.info("*********************clear memory cache");
	}

	public static void clearDb() {
		StoreDao.deleteAll();
		hits = 0;
		misses = 0;
		byteFetched = 0;
		byteStored = 0;
		items = 0;
		logger.info("*********************clear database cache");
	}
	
	
}
